using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SyncUdp.Utility
{
    using Newtonsoft.Json;
    using SyncUdp.Interface;
    using System;
    using System.Text;

    /// <summary>
    /// 自定义 Json 序列化工具的接口
    /// </summary>
    public interface IJsonUtility : ISingleton
    {
        /// <summary>
        /// 从 Json 字符串中获取对象
        /// </summary>
        /// <typeparam name="T">对象的类型</typeparam>
        /// <param name="jsonStr">Json 字符串</param>
        /// <returns></returns>
        public T GetObjectFromJson<T>(string jsonStr);

        /// <summary>
        /// 通过所给的字节数组，以 UTF-8 的形式反序列化成指定的对象
        /// </summary>
        /// <typeparam name="T">反序列化的对象类型</typeparam>
        /// <param name="buffer">所提供的字节数组</param>
        /// <returns></returns>
        public T GetObjectFromBytesWithUTF8<T>(byte[] buffer, int count = -1);
        
        /// <summary>
        /// 尝试通过所给的字节数组，以 UTF-8 的形式反序列化成指定的对象
        /// </summary>
        /// <typeparam name="T">反序列化的对象类型</typeparam>
        /// <param name="buffer">所提供的字节数组</param>
        /// <returns></returns>
        public bool TryGetObjectFromBytesWithUTF8<T>(byte[] buffer, out T value);

        /// <summary>
        /// 以 UTF-8 的形式将对象通过 Json 序列化成字节数组
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="serializableObject">可序列化的对象</param>
        /// <returns></returns>
        public byte[] GetBytesFromObjectWithUTF8<T>(T serializableObject);

        /// <summary>
        /// 以 UTF-8 的形式将对象通过 Json 序列化成字节数组
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="buffer">将结果存放到该参数中</param>
        /// <param name="serializableObject">可序列化的对象</param>
        /// <returns></returns>
        public void GetBytesFromObjectWithUTF8<T>(byte[] buffer, T serializableObject);
    }

    /// <summary>
    /// 自定义的 Json 序列化工具
    /// </summary>
    public class JsonUtility : AbstractSingleton, IJsonUtility
    {
        JsonSerializerSettings _setting;

        #region 方法实现
        protected override void OnInit()
        {
            _setting = new JsonSerializerSettings();
            JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
            {
                // 忽略空值，以减小 json 字符串长度
                _setting.NullValueHandling = NullValueHandling.Ignore;
                return _setting;
            });
        }

        public T GetObjectFromJson<T>(string jsonStr)
        {
            var data = JsonConvert.DeserializeObject<T>(jsonStr);
            return data;
        }

        public T GetObjectFromBytesWithUTF8<T>(byte[] buffer, int count = -1)
        {
            var jsonStr = Encoding.UTF8.GetString(buffer, 0, count == -1 ? buffer.Length : count);
            return GetObjectFromJson<T>(jsonStr);
        }

        public byte[] GetBytesFromObjectWithUTF8<T>(T serializableObject)
        {
            var jsonStr = JsonConvert.SerializeObject(serializableObject);
            var buffer = Encoding.UTF8.GetBytes(jsonStr);
            return buffer;
        }

        public void GetBytesFromObjectWithUTF8<T>(byte[] buffer, T serializableObject)
        {
            buffer = GetBytesFromObjectWithUTF8(serializableObject);
        }

        public bool TryGetObjectFromBytesWithUTF8<T>(byte[] buffer, out T value)
        {
            try
            {
                value = GetObjectFromBytesWithUTF8<T>(buffer);
                return true;
            }
            catch
            {
                value = default;
                return false;
            }
        }
        #endregion
    }
}

